const express = require('express');
const http = require('http');
const https = require('https');
const socketIo = require('socket.io');
const cors = require('cors');
const fs = require('fs');
const app = express();

const server = https.createServer({
    key: fs.readFileSync('./petcode.wang.key'), // 替换为你的私钥文件的路径
    cert: fs.readFileSync('./petcode.wang_bundle.crt') // 替换为你的证书文件的路径
}, app);
// const server = http.createServer(app);
app.use(express.json());  // 注意，这句代码只需要写一次，应放在文件的顶部

// app.use(cors());
app.use(cors({origin: '*'}));
// app.use(cors({
//     // origin: 'https://111.230.12.92'
//     origin: 'https://111.230.12.92', // or whatever your origin is
//     methods: ['GET', 'POST'], // or other methods as needed
//     allowedHeaders: ['Content-Type', 'Authorization'], // specify allowed headers here
// }));
// app.options('*', cors()) // include before other routes



// https://localhost:3000/hello
app.get('/hello', (req, res) => {
    console.log('Received request to /hello');
    res.json({ message: 'Hello, World!' });
});

app.post('/api/sendDeviceName', (req, res) => {
    const {deviceName} = req.body;
    console.log("/sendDeviceName");
    if (Object.keys(devicesList).includes(deviceName)) {
        res.send({message: 'Signal sent successfully.', data: true});
    } else {
        res.send({message: 'Device not found.', data: false});
    }
});

app.post('/api/sendDeviceToken', (req, res) => {
    const {deviceToken} = req.body;

    console.log("/sendDeviceToken");
    for (const devName in devicesList) {

        if (devicesList[devName].token === deviceToken) {
            res.send({message: 'check successfully.', data: true});
            return;
        }
    }
    res.send({message: 'check fail.', data: false});
});

app.post('/api/sendAdmingPassword', (req, res) => {
    const {password} = req.body;
    if (password === administrator.password) {
        const responseData = {
            message: 'check success.',
            data: {
                devices: { ...devicesList }, // 使用扩展运算符复制对象，避免直接引用
                clients: Array.from(clientList.values()) // 将 Map 转换为数组
            }
        };
        res.json(responseData); // 使用 res.json() 方法将数据转换为 JSON 格式发送
        return
    }
    res.send({message: 'check fail.', data: false});
});

function generateToken() {
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let token = '';
    for (let i = 0; i < 8; i++) {
        token += characters.charAt(Math.floor(Math.random() * characters.length));
    }
    return token;
}

app.post('/api/changeDeviceToken', (req, res) => {
    const {deviceName} = req.body;
    if (devicesList[deviceName]) devicesList[deviceName].token = generateToken()
    else return res.send({message: 'change fail.', data: false});
    res.send({message: 'change success.', data: true});
});

// const server = http.createServer(app);
const io = socketIo(server, {
    cors: {
        origin: "*",
        methods: ["GET", "POST"],
        allowedHeaders: ["my-custom-header"],
        credentials: true
    }
});

const administrator = {
    username: 'czy',
    password: 'petcode',
}

let devicesList = {
    "1": {
        socket: null,
        token: "1"
    },
    // "devices01": {
    //     socket: null,
    //     token: "PeTCode1"
    // },
    "devices02": {
        socket: null,
        token: "PeTCode2"
    },
    "devices03": {
        socket: null,
        token: "PeTCode3"
    },

    "devices04": {
        socket: null,
        token: "PeTCode4"
    }
}
let clientList = new Map() //TODO 做设备同时登录限制数量判断

io.on('connection', (socket) => {
    console.log("有东西连上了")

    socket.on("device_Online", (deviceName) => {
        console.log("设备端" + socket.id)
        if (Object.keys(devicesList).includes(deviceName)) devicesList[deviceName].socket = socket
    })

    socket.on("client_Online", (deviceToken) => {
        console.log("客户端" + socket.id)
        // clientList.push(socket)
        for (const devName in devicesList) {

            if (devicesList[devName].token === deviceToken && devicesList[devName].socket) {
                // 将客户端添加到客户端列表
                clientList.set(socket.id, {device: devName, socket: socket});

                // 给设备端发送用户已经登录与用户socket_id
                devicesList[devName].socket.emit("client_connected", socket.id)
                break
            } else {
                console.log("设备端还没上线")
            }

        }
    })

    // 处理设备端发送过来的offer
    socket.on('offer', (offer, clientId) => {
        const client = clientList.get(clientId)
        if (client) client.socket.emit('offer', offer);
        // for (const client of clientList) {
        //     if(client.id === clientId){
        //         //给客户端发送设备端的本地描述文件
        //         client.emit('offer', offer);
        //         break
        //     }
        // }
    });

    // 处理客户端发送过来的answer
    socket.on('answer', (answer, deviceToken) => {
        for (const devName in devicesList) {

            if (devicesList[devName].token === deviceToken) {
                // 给设备端发送用户已经登录与用户socket_id
                devicesList[devName].socket.emit("answer", answer)
                break
            }

        }
    });

    // 处理任意一方发送过来的candidate
    socket.on('candidate', (candidate, Msg) => {
        const {type, token} = Msg
        if (type === 'device') {
            const clientId = token
            const client = clientList.get(clientId)
            if (client) client.socket.emit('candidate', candidate);
            // for (const client of clientList) {
            //     if(client.id === token){
            //         //给客户端发送candidate
            //         client.emit('candidate', candidate);
            //         break
            //     }
            // }
        } else {
            for (const devName in devicesList) {
                if (devicesList[devName].token === token) {
                    // 给设备端发送candidate
                    devicesList[devName].socket.emit("candidate", candidate)
                    break
                }
            }
        }
    });

    // 当设备断开连接时，将其从用户列表中删除
    socket.on('disconnect', () => {
        console.log('User disconnected: ' + socket.id);
        const clientInfo = clientList.get(socket.id);
        if (clientInfo) {
            const deviceSocket = devicesList[clientInfo.device].socket;
            deviceSocket.emit('client_disconnected', socket.id);
            clientList.delete(socket.id);
        }
    });

});

const port = process.env.PORT || 3000;
server.listen(port, () => console.log(`Server is running on port ${port}`));
